package ln.gather.jsr.jcache.integration;

import javax.cache.Cache;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CacheWriterException;
import java.io.*;
import java.util.Arrays;
import java.util.logging.Logger;

/**
 * @see FallbackStorage
 * 基于文件实现
 */
public class FileFallbackStorage extends AbstractFallbackStorage<Object, Object>{

    private final Logger logger = Logger.getLogger(this.getClass().getName());

    /**
     * 文件地址前缀常量
     */
    private final File CACHE_FALLBACK_DIRECTORY = new File("cache/fallback/");

    public FileFallbackStorage() {
        super(Integer.MAX_VALUE);
        mikerCacheFallbackDirectory(CACHE_FALLBACK_DIRECTORY);
    }

    private void mikerCacheFallbackDirectory(File directory) {
        if(!directory.exists() && !directory.mkdirs()) {
            throw new IllegalStateException("创建缓存文件夹失败");
        }
    }

    private File toTargetFile(Object key) {
        return new File(CACHE_FALLBACK_DIRECTORY, key.toString() + ".dat");
    }

    /**
     * 销毁缓存: 销毁文件
     */
    @Override
    public void destroy() {
        if(CACHE_FALLBACK_DIRECTORY.exists()) {
            Arrays.stream(CACHE_FALLBACK_DIRECTORY.listFiles()).forEach(File::delete);
        }
    }

    /**
     * 加载缓存对象：从文件中加载
     */
    @Override
    public Object load(Object key) throws CacheLoaderException {
        File targetFile = toTargetFile(key);
        if(!targetFile.exists() && !targetFile.canRead()) {
            throw new IllegalStateException("缓存文件不存在且不可读");
        }
        Object value;
        try(FileInputStream inputStream = new FileInputStream(targetFile);
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)
        ) {
            value = objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return value;
    }

    /**
     * 写入缓存对象：写入缓存对象到文件中
     */
    @Override
    public void write(Cache.Entry<?, ?> entry) throws CacheWriterException {
        Object key = entry.getKey();
        Object value = entry.getValue();
        File targetFile = toTargetFile(key);
        if(!targetFile.exists() && !targetFile.canWrite()) {
            throw new IllegalStateException("缓存文件不存在且不可写");
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)
        ){
            objectOutputStream.writeObject(value);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除缓存对象：写入缓存对象到文件中
     */
    @Override
    public void delete(Object key) throws CacheWriterException {
        File targetFile = toTargetFile(key);
        if(targetFile.exists()) {
            targetFile.delete();
        }
    }
}
